package com.interview.client.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException;
import java.util.*;

public class HTTPUtils {
    /**
     * 初始化连接
     *
     * @param url 连接地址
     * @param headers 请求头
     * @return 连接
     * @throws IOException
     */
    private static HttpURLConnection getConnection(String url, Map<String, String> headers) throws IOException {
        URL httpUrl = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) httpUrl.openConnection();
        connection.setConnectTimeout(15000);
        connection.setReadTimeout(60000);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                connection.addRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        return connection;
    }

    /**
     * 无自定请求头初始化连接
     *
     * @param url 连接地址
     * @return 连接
     * @throws IOException
     */
    private static HttpURLConnection getConnection(String url) throws IOException {
        return getConnection(url, null);
    }

    /**
     * 处理返回数据
     *
     * @param connection 连接
     * @return 返回的json
     * @throws IOException
     */
    private static String handleResponse(HttpURLConnection connection) throws IOException {
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            int code = connection.getResponseCode();
            if (200 == code) {
                is = connection.getInputStream();
                isr = new InputStreamReader(is, StandardCharsets.UTF_8);
                br = new BufferedReader(isr);
                StringBuilder sb = new StringBuilder();
                String s = null;
                while ((s = br.readLine()) != null) {
                    sb.append(s).append("\r\n");
                }
                return sb.toString();
            } else {
                throw new RuntimeException("handleResponse Error With Code:" + code);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                is.close();
            }
            if (isr != null) {
                isr.close();
            }
            if (br != null) {
                br.close();
            }
        }
        throw new RemoteException();
    }

    /**
     * 使用get方法访问服务器资源
     * @param url 连接地址
     * @param headers 请求头
     * @return
     * @throws IOException
     */
    public static String doGet(String url, Map<String, String> headers) throws IOException {

        HttpURLConnection connection = null;
        try {
            connection = getConnection(url, headers);
            connection.setRequestMethod("GET");
            connection.connect();
            String result = handleResponse(connection);
            return result;
        } catch (IOException e) {
            throw e;
        } finally {
            assert connection != null;
            connection.disconnect();
        }
    }

    /**
     *使用POST方法上传文件
     * @param url 连接地址
     * @param file 需要上传的文件
     * @return
     * @throws IOException
     */
    public static String doPostAndSendFiles(String url, File file) throws IOException {

        HttpURLConnection connection = null;
        OutputStream os = null;
        StringBuilder requestParams = new StringBuilder();
        final String BOUNDARY = "--" + UUID.randomUUID().toString();
        final String newLine = "\r\n";
        final String boundaryPrefix = "--";
        try {
            //配置请求头
            connection = getConnection(url, null);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Charsert", "UTF-8");
            connection.setRequestProperty("Accept", "*/*");
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36");
            //请求的参数
            requestParams.append(boundaryPrefix).append(BOUNDARY).append(newLine);
            requestParams.append("Content-Disposition: form-data; name=\"uploadFile\"; filename=\"").append(file.getName()).append("\"").append(newLine);
            requestParams.append("Content-Type: application/octet-stream")
                    .append(newLine).append(newLine);

            os = new DataOutputStream(connection.getOutputStream());
            os.write(requestParams.toString().getBytes());
            os.write(handleFile(file));
            os.write(newLine.getBytes());
            byte[] end_data = (newLine + boundaryPrefix + BOUNDARY + boundaryPrefix + newLine).getBytes();
            os.write(end_data);
            os.flush();
            connection.connect();
            String result = handleResponse(connection);
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            assert connection != null;
            connection.disconnect();
            assert os != null;
            os.close();
        }
        return null;
    }

    /**
     * 将文件转为byte数组
     * @param file
     * @return
     * @throws IOException
     */
    private static byte[] handleFile(File file) throws IOException {

        FileInputStream fis = new FileInputStream(file);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            int len;
            byte[] buffer = new byte[1024];
            while ((len = fis.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            return baos.toByteArray();
        } finally {
            fis.close();
            baos.close();
        }

    }

    /**
     *获取下载文件
     *
     * @param url 连接地址
     * @param filePath 文件路径
     * @return
     * @throws IOException
     */
    public static String doGetAndDownloadFile(String url,String filePath) throws IOException {

        HttpURLConnection connection = null;
        try {
            connection = getConnection(url, null);
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.connect();
            String result = downloadFile(connection.getOutputStream(),filePath);
            return result;
        } catch (IOException e) {
            throw e;
        } finally {
            assert connection != null;
            connection.disconnect();
        }


    }

    private static String downloadFile(OutputStream os, String filePath) throws IOException {
        FileInputStream fis = null;
        try{
            File file = new File(filePath);
            if (!file.exists()){
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0){
                os.write(b, 0, length);
            }
            return "文件上传成功，保存在：" + filePath;
        }
        catch (IOException e){
            throw e;
        }
        finally{
            if (os != null){
                try{
                    os.close();
                }
                catch (IOException e1){
                    e1.printStackTrace();
                }
            }
            if (fis != null){
                try{
                    fis.close();
                }
                catch (IOException e1){
                    e1.printStackTrace();
                }
            }
        }
    }
}